#include "stdafx.h"
#include "AvisynthScriptGenerator.h"
#include "FrameRate.h"

#undef GetTempPath

using namespace System;
using namespace System::Text;
using namespace System::IO;
using namespace System::Collections::Generic;

namespace ManagedVC1
{
    String^ AvisynthScriptGenerator::Generate(System::Collections::Generic::List<MediaSource^>^ sources)
    {
        return Generate(sources, Colorspace::YV12, FrameRates::NTSCp->Rate);
    }

    String^ AvisynthScriptGenerator::Generate(List<MediaSource^>^ sources, Colorspace convColor, double defaultFrameRate)
    {
        List<String^> srcFiles;
        StringBuilder strbld;
        int i = 0;
        bool hasInterlacedTrack = false;

        for each (MediaSource^ s in sources)
        {
            if (s->IsInterlaced)
            {
                hasInterlacedTrack = true;
                strbld.AppendLine("LoadPlugin(\"TDeint.dll\")");
                break;
            }
        }

        for each (MediaSource^ ms in sources)
        {
            if (srcFiles.Contains(ms->FileName)) continue;

            double fr = (ms->FrameRate > 0) ? ms->FrameRate : defaultFrameRate;
            strbld.AppendFormat(System::Globalization::CultureInfo::InvariantCulture, 
                "c{0}=DirectShowSource(\"{1}\", fps={2}, audio={3})",
                sources->IndexOf(ms), ms->FileName, fr, ms->IncludeAudio.ToString());
            strbld.AppendLine();
            srcFiles.Add(ms->FileName);
            i++;
        }

        i = 0;
        for each (MediaSource^ ms in sources)
        {
            if (i > 0) strbld.Append("+");

            strbld.AppendFormat("c{0}", srcFiles.IndexOf(ms->FileName));

            bool isNTSC = (ms->FrameRate == 0 || Math::Round(ms->FrameRate, 2) == FrameRates::NTSCp->Rate);
            if (!isNTSC)
            {
                strbld.Append(".Bob(height=480).BicubicResize(720,480).ConvertFPS(60000, 1001).SeparateFields.SelectEvery(4,0,3).Weave()");
            }

            if (ms->VideoResolution != nullptr && ms->VideoResolution->Width == 352 && ms->VideoResolution->Height == 480)
            {
                strbld.Append(".BicubicResize(640, 480)");
            }

            if (ms->IncludeAudio) strbld.Append(".ResampleAudio(44100)");

            double fr = (ms->FrameRate > 0) ? ms->FrameRate : defaultFrameRate;
            strbld.AppendFormat(".Trim({0},{1})", ConvertTimeToFrame(ms->MarkIn, fr), ConvertTimeToFrame(ms->MarkOut, fr));

            if (ms->IsInterlaced)
            {
                if (convColor != Colorspace::None)
                {
                    strbld.Append(".ConvertToYV12()");
                }
                strbld.Append(".AssumeFrameBased().TDeint()");
                if (convColor != Colorspace::None && convColor != Colorspace::YV12)
                {
                    strbld.Append(".ConvertTo");
                    strbld.Append(convColor.ToString());
                    strbld.Append("()");
                }
            }

            i++;
        }
        strbld.AppendLine();
        if (!hasInterlacedTrack && convColor != Colorspace::None)
        {
            strbld.Append("ConvertTo");
            strbld.Append(convColor.ToString());
            strbld.Append("()");
        }

        String^ filename = Path::Combine(Path::GetTempPath(), Guid::NewGuid().ToString() + ".avs");
        File::WriteAllText(filename, strbld.ToString());

        return filename;
    }

    int AvisynthScriptGenerator::ConvertTimeToFrame(TimeSpan inputTime, double frameRate)
    {
        //if zero or not set then return zero
        //AVISynth will automatically set at beginning of clip (if markin) or end of clip (if markout)
        if (inputTime == TimeSpan::Zero || inputTime == TimeSpan::MinValue || inputTime == TimeSpan::MaxValue)
            return 0;

        //round to the next frame to avoid crazy scene change glitches with going to the previous frame
        return (int)Math::Ceiling(inputTime.TotalSeconds * frameRate);
    }
}